package cn.darkhorse.ticket.production.service.impl;

import cn.darkhorse.ticket.basis.pojo.TicketProduct;
import cn.darkhorse.ticket.basis.pojo.TicketProductType;
import cn.darkhorse.ticket.basis.pojo.TicketRouting;
import cn.darkhorse.ticket.basis.service.TicketProductService;
import cn.darkhorse.ticket.basis.service.TicketProductTypeService;
import cn.darkhorse.ticket.basis.service.TicketRoutingService;
import cn.darkhorse.ticket.code.RepeatCheck;
import cn.darkhorse.ticket.constants.TicketConstants;
import cn.darkhorse.ticket.production.dto.TicketProductionPlanInfoDTO;
import cn.darkhorse.ticket.production.pojo.TicketInfo;
import cn.darkhorse.ticket.production.pojo.TicketProductionPlanInfo;
import cn.darkhorse.ticket.production.mapper.TicketProductionPlanInfoMapper;
import cn.darkhorse.ticket.production.pojo.TicketProductionPlanProductInfo;
import cn.darkhorse.ticket.production.pojo.TicketTask;
import cn.darkhorse.ticket.production.service.TicketInfoService;
import cn.darkhorse.ticket.production.service.TicketProductionPlanInfoService;
import cn.darkhorse.ticket.production.service.TicketProductionPlanProductInfoService;
import cn.darkhorse.ticket.production.vo.TicketInfoVO;
import cn.darkhorse.ticket.production.vo.TicketProductionPlanInfoVO;
import cn.darkhorse.ticket.production.vo.TicketProductionPlanInfoViewVO;
import cn.darkhorse.ticket.production.vo.TicketProductionPlanProductInfoVO;
import cn.darkhorse.ticket.service.MesCodeRulesService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.ISysDictTypeService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 生产计划信息 服务实现类
 * </p>
 *
 * @author maoguanjun
 * @since 2024-01-19
 */
@Service
public class TicketProductionPlanInfoServiceImpl extends ServiceImpl<TicketProductionPlanInfoMapper, TicketProductionPlanInfo> implements TicketProductionPlanInfoService {
    @Resource
    private ISysDictTypeService iSysDictTypeService;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private RepeatCheck<TicketProductionPlanInfo> repeatCheck;
    @Resource
    private RepeatCheck<TicketInfo> repeatCheckTicket;
    @Resource
    private TicketProductionPlanProductInfoService ticketProductionPlanProductInfoService;
    @Resource
    private TicketProductService ticketProductService;
    @Resource
    private TicketProductTypeService ticketProductTypeService;
    @Resource
    private TicketInfoService ticketInfoService;
    @Resource
    private MesCodeRulesService mesCodeRulesService;
    @Resource
    private TicketRoutingService ticketRoutingService;
    /**
     * 列表
     *
     * @param dto
     * @return
     */
    @Override
    public TableDataInfo listAll(TicketProductionPlanInfoDTO dto) {
        LambdaQueryWrapper<TicketProductionPlanInfo> wrapper=new LambdaQueryWrapper<>();
        if(null!=dto.getBeginTime()){
            wrapper.ge(TicketProductionPlanInfo::getPlanedDeliveryDate,dto.getBeginTime());
        }
        if(null!=dto.getEndTime()){
            wrapper.le(TicketProductionPlanInfo::getPlanedDeliveryDate,dto.getEndTime());
        }
        if(StringUtils.isNotBlank(dto.getDataCode())){
            wrapper.like(TicketProductionPlanInfo::getCode,dto.getDataCode());
        }
        if(null!=dto.getStatus()){
            wrapper.eq(TicketProductionPlanInfo::getStatus,dto.getStatus());
        }
        wrapper.orderByDesc(TicketProductionPlanInfo::getGmtCreate);
        List<TicketProductionPlanInfo> list = list(wrapper);
        List<TicketProductionPlanInfoVO> voList=new LinkedList<>();
        // 生产计划状态
        List<SysDictData> planSection = iSysDictTypeService.selectDictDataByType("production_plan_status");
        Map<String, String> planData = planSection.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        // 生产计划来源
        List<SysDictData> planSource = iSysDictTypeService.selectDictDataByType("production_plan_source");
        Map<String, String> sourceData = planSource.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //获取用户
        List<SysUser> sysUsers = sysUserMapper.selectUserListNoAuth(new SysUser());
        Map<Long, String> userMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserId,SysUser::getNickName));

        if(null!=list&&list.size()>0){
            list.forEach(item->{
                TicketProductionPlanInfoVO vo=new TicketProductionPlanInfoVO();
                BeanUtils.copyProperties(item,vo);
                if(planData.containsKey(vo.getStatus().toString())){
                    vo.setStatusName(planData.get(vo.getStatus().toString()));
                }
                if(sourceData.containsKey(vo.getSource().toString())){
                    vo.setSourceName(sourceData.get(vo.getSource().toString()));
                }
                if(userMap.containsKey(vo.getCreator())){
                    vo.setCreatorName(userMap.get(vo.getCreator()));
                }
                if(userMap.containsKey(vo.getModifier())){
                    vo.setModifierName(userMap.get(vo.getModifier()));
                }
                voList.add(vo);
            });
        }
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setMsg("查询成功");
        rspData.setRows(voList);
        rspData.setTotal(new PageInfo(list).getTotal());
        return rspData;
    }

    /**
     * 保存
     *
     * @param info
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean savePlan(TicketProductionPlanInfoVO info) {
        info.setName(info.getCode());
        //编码校验
        repeatCheck.repeatCode(this,info, TicketConstants.BUSINESS_TYPE_SCJH);
        if(info.getPlanedStartTime().compareTo(info.getPlanedEndTime())>0){
            throw new ServiceException("计划开始时间不能晚于计划结束时间!");
        }
        if(null!=info.getId()){
            LambdaQueryWrapper<TicketProductionPlanProductInfo> planWrapper=new LambdaQueryWrapper<>();
            planWrapper.eq(TicketProductionPlanProductInfo::getPlanId,info.getId());
            ticketProductionPlanProductInfoService.remove(planWrapper);
        }
        boolean infoResult = saveOrUpdate(info);
        List<TicketProductionPlanProductInfo> productionPlanProductInfoList = info.getProductionPlanProductInfoList();
        if(null!=productionPlanProductInfoList&&productionPlanProductInfoList.size()>0) {
            productionPlanProductInfoList.forEach(item -> {
                item.setPlanId(info.getId());
                if(item.getPlanedEndTime().compareTo(info.getPlanedEndTime())>0){
                    throw new ServiceException("产品的计划结束不能迟于整体计划的结束时间!");
                }
                if(item.getPlanedDeliveryDate().compareTo(info.getPlanedDeliveryDate())>0){
                    throw new ServiceException("产品的计划交期不能迟于整体计划的计划交期!");
                }
            });
        }else {
            throw new ServiceException("尚未添加产品!");
        }
        boolean productResult = ticketProductionPlanProductInfoService.saveOrUpdateBatch(productionPlanProductInfoList);
        return infoResult&&productResult;
    }

    /**
     * 查看
     *
     * @param dataId
     * @return
     */
    @Override
    public TicketProductionPlanInfoViewVO view(Long dataId) {
        TicketProductionPlanInfo data=getById(dataId);
        TicketProductionPlanInfoViewVO vo=new TicketProductionPlanInfoViewVO();
        if(null!=data){
            BeanUtils.copyProperties(data,vo);
            // 生产计划状态
            List<SysDictData> planSection = iSysDictTypeService.selectDictDataByType("production_plan_status");
            Map<String, String> planData = planSection.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
            // 生产计划来源
            List<SysDictData> planSource = iSysDictTypeService.selectDictDataByType("production_plan_source");
            Map<String, String> sourceData = planSource.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
            //获取用户
            List<SysUser> sysUsers = sysUserMapper.selectUserListNoAuth(new SysUser());
            Map<Long, String> userMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserId,SysUser::getNickName));
            if(planData.containsKey(vo.getStatus().toString())){
                vo.setStatusName(planData.get(vo.getStatus().toString()));
            }
            if(sourceData.containsKey(vo.getSource().toString())){
                vo.setSourceName(sourceData.get(vo.getSource().toString()));
            }
            if(userMap.containsKey(vo.getCreator())){
                vo.setCreatorName(userMap.get(vo.getCreator()));
            }
            if(userMap.containsKey(vo.getModifier())){
                vo.setModifierName(userMap.get(vo.getModifier()));
            }
            LambdaQueryWrapper<TicketProductionPlanProductInfo> planWrapper=new LambdaQueryWrapper<>();
            planWrapper.eq(TicketProductionPlanProductInfo::getPlanId,vo.getId());
            List<TicketProductionPlanProductInfo> list = ticketProductionPlanProductInfoService.list(planWrapper);
            List<TicketProductionPlanProductInfoVO> voList=new ArrayList<>();
            List<TicketProductType> typeList = ticketProductTypeService.list();
            Map<Long, String> collect = typeList.stream().collect(Collectors.toMap(TicketProductType::getId, TicketProductType::getName));
            list.forEach(item->{
                TicketProductionPlanProductInfoVO itemVO=new TicketProductionPlanProductInfoVO();
                BeanUtils.copyProperties(item,itemVO);
                TicketProduct product = ticketProductService.getById(item.getProductId());
                if(null!=product){
                    itemVO.setProductName(product.getName());
                    itemVO.setModel(product.getModel());
                    itemVO.setQuality(product.getQuality());
                    itemVO.setWeight(product.getWeight());
                    itemVO.setProductTypeName(collect.containsKey(product.getProductTypeId())?collect.get(product.getProductTypeId()):"");
                }
                voList.add(itemVO);
            });
            vo.setProductionPlanProductInfoList(voList);
        }
        return vo;
    }

    /**
     * 关闭计划
     *
     * @param dataId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean close(Long dataId) {
        TicketProductionPlanInfo data=getById(dataId);
        if(null!=data){
            if(TicketConstants.PLAN_STATUS_NOT_CREATE!=data.getStatus()){
                throw new ServiceException("只有未生成工单状态的计划可进行关闭!");
            }
            //关闭
            data.setStatus(TicketConstants.PLAN_STATUS_CLOSE);
            boolean result = updateById(data);
            LambdaUpdateWrapper<TicketProductionPlanProductInfo> wrapper=new LambdaUpdateWrapper<>();
            wrapper.eq(TicketProductionPlanProductInfo::getPlanId,dataId);
            wrapper.set(TicketProductionPlanProductInfo::getStatus,TicketConstants.PLAN_PRODUCT_STATUS_CLOSE);
            ticketProductionPlanProductInfoService.update(wrapper);
            return result;
        }
        return false;
    }

    /**
     * 创建工单
     *
     * @param dataId       计划Id
     * @param dataDetailId 产品明细Id
     * @return
     */
    @Override
    public String createTicket(Long dataId, Long dataDetailId) {
        Long userId = SecurityUtils.getUserId();
        String msg="";
        boolean produceFlag=false;
        TicketProductionPlanInfo planInfo = getById(dataId);
        if(null==planInfo){
            throw new ServiceException("无数据");
        }
        if(TicketConstants.PLAN_STATUS_CLOSE==planInfo.getStatus()){
            throw new ServiceException("计划已关闭！");
        }
        //批量生成
        if(null==dataDetailId){
            //获取未生成工单产品
            List<TicketProductionPlanProductInfo> list =getProduct(dataId);
            Long allProductNum = getALLProductNum(dataId);
            if(null!= list&& list.size()>0){
                for (TicketProductionPlanProductInfo item : list) {
                    if(item.getStatus()==TicketConstants.YES){
                        continue;
                    }
                    boolean hasProduce = ticketProductService.hasProduce(item.getProductId());
                    if(!hasProduce){
                        //msg+=" 产品"+item.getProductName()+" ";
                        msg+=" "+item.getProductName()+" ";
                        continue;
                    }
                    boolean result = saveEntity(dataId, item, planInfo, userId);
                    produceFlag=true;

                }
                if(StringUtils.isNotBlank(msg)){
                    if(produceFlag){
                        msg=StringUtils.format("操作完成，{}产品未关联工艺路线未生成工单，请在产品管理功能下关联工艺路线后再设置",msg);
                    }else{
                        //没有其他生成工单
                        if(allProductNum==list.size()){
                            throw new ServiceException("该计划的产品未关联工艺路线，请去关联产品工艺路线!");
                        }else{
                            msg=StringUtils.format("操作完成，{}产品未关联工艺路线未生成工单，请在产品管理功能下关联工艺路线后再设置",msg);
                        }
                    }
                }else{
                    msg="工单生成完毕!";
                }
            }
        //单个生成
        }else{
            TicketProductionPlanProductInfo planProduct = ticketProductionPlanProductInfoService.getById(dataDetailId);
            if(planProduct.getStatus()==TicketConstants.YES){
                throw new ServiceException("已生成工单,无法再次生成！");
            }
            boolean hasProduce = ticketProductService.hasProduce(planProduct.getProductId());
            if(!hasProduce){
                throw new ServiceException("该产品未关联工艺路线，请在产品管理功能下关联工艺路线后再设置!");
            }
            boolean result = saveEntity(dataId, planProduct, planInfo, userId);
            msg="工单生成完毕!";
        }
        //更新计划状态
        upPlanStatus(planInfo);
        return msg;
    }

    /**
     * 获取未生成工单计划产品
     *
     * @param dataId
     * @return
     */
    @Override
    public List<TicketProductionPlanProductInfo> getProduct(Long dataId) {
        LambdaQueryWrapper<TicketProductionPlanProductInfo> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(TicketProductionPlanProductInfo::getPlanId,dataId);
        wrapper.eq(TicketProductionPlanProductInfo::getStatus,TicketConstants.PLAN_PRODUCT_STATUS_NOT_CREATE);
        List<TicketProductionPlanProductInfo> list = ticketProductionPlanProductInfoService.list(wrapper);
        return list;
    }
    public Long getALLProductNum(Long dataId) {
        LambdaQueryWrapper<TicketProductionPlanProductInfo> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(TicketProductionPlanProductInfo::getPlanId,dataId);
        return ticketProductionPlanProductInfoService.count(wrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean saveEntity(Long dataId,TicketProductionPlanProductInfo planProduct,TicketProductionPlanInfo planInfo,Long userId){
        TicketProduct product = ticketProductService.getById(planProduct.getProductId());
        LambdaQueryWrapper<TicketRouting> routingWrapper=new LambdaQueryWrapper<>();
        routingWrapper.eq(TicketRouting::getCode, product.getRoutingCode());
        List<TicketRouting> routingList = ticketRoutingService.list(routingWrapper);
        TicketInfoVO vo=new TicketInfoVO();
        String code = mesCodeRulesService.getCode(TicketConstants.BUSINESS_TYPE_GD);
        vo.setCode(code);
        vo.setIsAutomatically(true);
        vo.setPlanId(dataId);
        vo.setProductId(planProduct.getProductId());
        vo.setProductCode(planProduct.getProductCode());
        vo.setCustomerId(planInfo.getCustomerId());
        vo.setPlanNum(planProduct.getPlanNum());
        vo.setCreator(userId);
        vo.setModifier(userId);
        vo.setPlanedDeliveryDate(planProduct.getPlanedDeliveryDate());
        vo.setPlanedStartTime(planProduct.getPlanedStartTime());
        vo.setPlanedEndTime(planProduct.getPlanedEndTime());
        vo.setRemark(planInfo.getRemark());
        vo.setSource(TicketConstants.NO);
        List<TicketTask> taskList=new ArrayList<>();
        routingList.forEach(item->{
            TicketTask task=new TicketTask();
            task.setTicketInfoCode(vo.getCode());
            task.setProcedureCode(item.getProcedureCode());
            task.setOrderNumber(item.getOrderNumber());
            task.setProcedureName(item.getProcedureName());
            task.setPlanedStartTime(vo.getPlanedStartTime().toLocalDate());
            task.setPlanedEndTime(vo.getPlanedEndTime().toLocalDate());
            //增加质检状态
            task.setInspectionStates(item.getProcedureStates());
            taskList.add(task);
        });
        vo.setTicketTask(taskList);
        String newCode = repeatCheckTicket.repeatCode(ticketInfoService, vo, TicketConstants.BUSINESS_TYPE_GD);
        if(null!=newCode){
            vo.setCode(newCode);
        }
        boolean result = ticketInfoService.saveTicket(vo);
        planProduct.setRelatedTicketNum(vo.getCode());
        planProduct.setStatus(TicketConstants.YES);
        ticketProductionPlanProductInfoService.updateById(planProduct);
        return result;
    }

    /**
     * 更新计划状态
     * @param planInfo
     */
    public void upPlanStatus(TicketProductionPlanInfo planInfo){
        LambdaQueryWrapper<TicketProductionPlanProductInfo> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(TicketProductionPlanProductInfo::getPlanId,planInfo.getId());
        wrapper.eq(TicketProductionPlanProductInfo::getStatus,TicketConstants.PLAN_PRODUCT_STATUS_NOT_CREATE);
        long count = ticketProductionPlanProductInfoService.count(wrapper);
        wrapper.clear();
        wrapper.eq(TicketProductionPlanProductInfo::getPlanId, planInfo.getId());
        wrapper.eq(TicketProductionPlanProductInfo::getStatus,TicketConstants.PLAN_PRODUCT_STATUS_CREATE);
        long count1 = ticketProductionPlanProductInfoService.count(wrapper);
        if(count>0){
            //部分生成
            if(count1>0){
                planInfo.setStatus(TicketConstants.PLAN_STATUS_PART_CREATE);
            //全部未生成
            }else{
                planInfo.setStatus(TicketConstants.PLAN_STATUS_NOT_CREATE);
            }
        }else{
            //全部生成
            if(count1>0) {
                planInfo.setStatus(TicketConstants.PLAN_STATUS_ALL_CREATE);
            }
        }
        updateById(planInfo);
    }
}
